package cmd

import (
	"encoding/json"
	"fmt"
	"github.com/aliyun/alibabacloud-kms-agent/internal/cache"
	"github.com/aliyun/alibabacloud-kms-agent/internal/conf"
	"github.com/aliyun/alibabacloud-kms-agent/internal/kms"
	"github.com/aliyun/alibabacloud-kms-agent/internal/logger"
	"github.com/aliyun/alibabacloud-kms-agent/internal/service"
	"github.com/spf13/cobra"
	"os"
	"path/filepath"
)

var agentCmd = &cobra.Command{
	Use:   "agent",
	Short: "run the alibabacloud-kms-agent",
	Run: func(cmd *cobra.Command, args []string) {
		var configPath string
		// Specify configuration file
		if len(args) > 0 {
			configPath = args[0]
		}
		// Find configuration files in the same directory
		exePath, err := os.Executable()
		if err != nil {
			_, _ = fmt.Fprintf(os.Stderr, "cat get execute opath: %v\n", err)
			os.Exit(1)
		}

		exeDir := filepath.Dir(exePath)
		if fileExists(exeDir + "/" + "config.toml") {
			configPath = exeDir + "/" + "config.toml"
		}

		startAgent(configPath)
	},
}

func startAgent(configPath string) {
	var cfg conf.Config
	var err error
	if configPath == "" {
		cfg = conf.DefaultConfig()
	} else {
		cfg, err = conf.LoadConfigFormFile(configPath)
		if err != nil {
			_, _ = fmt.Fprintf(os.Stderr, "failed to load config from file: %v\n", err)
			os.Exit(1)
		}
	}
	{
		b, _ := json.Marshal(cfg)
		_, _ = fmt.Fprintf(os.Stderr, "success load config: %s\n", string(b))
	}

	lw, err := logger.NewLogger(cfg.Log)
	if err != nil {
		_, _ = fmt.Fprintf(os.Stderr, "failed to initialize logger: %v\n", err)
		os.Exit(1)
	}

	cacheStore, err := cache.NewCacheStore(cfg.Cache)
	if err != nil {
		_, _ = fmt.Fprintf(os.Stderr, "failed to initialize cache store: %v\n", err)
		os.Exit(1)
	}

	kmsClient, err := kms.NewKeyManagementService(cfg.Kms)
	if err != nil {
		_, _ = fmt.Fprintf(os.Stderr, "failed to initialize kms: %v\n", err)
		os.Exit(1)
	}
	_, _ = fmt.Fprintf(os.Stdout, "initialize kms with crendentials: %v\n", kmsClient.GetCredentialType())

	err = kmsClient.SelfCheck()
	if err != nil {
		_, _ = fmt.Fprintf(os.Stderr, "kms self check failed: %v\n", err)
		os.Exit(1)
	}

	server, err := service.NewServer(cfg.Server, cacheStore, kmsClient, lw)
	if err != nil {
		_, _ = fmt.Fprintf(os.Stderr, "failed to initialize http server: %v\n", err)
		os.Exit(1)
	}

	// start server
	server.Serve()
}

func fileExists(filename string) bool {
	info, err := os.Stat(filename)
	if os.IsNotExist(err) {
		return false
	}
	return err == nil && !info.IsDir()
}
